#pragma  once
#include <memory>
#include <vector>
#include "pde_export.h"
#include "glm/vec3.hpp"
#include <string>

namespace pde {

	typedef glm::ivec3 Size;
	typedef glm::dvec3 Spacing;
	typedef glm::dvec3 Origin;

	class pde_export VolumeShort {
	public:

		static std::shared_ptr<VolumeShort> New();
		bool Create(short default_val, short* voxels);
		bool Create(Size size, Spacing spacing, Origin origin, short default_val = 0, short* pixels = nullptr);

		Size& get_size() { return size_; }
		Spacing& get_spacing() { return spacing_; }
		Origin& get_origin() { return origin_; }
		int get_nvox() { return size_[0] * size_[1] * size_[2]; }
		short* get_voxels() { return voxels_; }

		void save_volume(const std::string& fn);
		void load_volume(const std::string& fn);

	private:
		Size size_;
		Spacing spacing_;
		Origin origin_;
		short* voxels_;

	};

	class pde_export VolumeUChar {
	public:

		static std::shared_ptr<VolumeUChar> New();
		bool Create(unsigned char default_val, unsigned char * voxels);
		bool Create(Size size, Spacing spacing, Origin origin, unsigned char default_val = 0,unsigned char* pixels = nullptr);

		Size& get_size() { return size_; }
		Spacing& get_spacing() { return spacing_; }
		Origin& get_origin() { return origin_; }
		int get_nvox() { return size_[0] * size_[1] * size_[2]; }
		unsigned char* get_voxels() { return voxels_; }

		void save_volume(const std::string& fn,const std::string& info);
		std::string load_volume(const std::string& fn);

	private:
		Size size_;
		Spacing spacing_;
		Origin origin_;
		unsigned char* voxels_;

	};

	class pde_export VolumeFloat {
	public:

		static std::shared_ptr<VolumeFloat> New();
		bool Create(float default_val, float* voxels);
		bool Create(Size size, Spacing spacing, Origin origin, float default_val = 0, float* pixels = nullptr);

		Size& get_size() { return size_; }
		Spacing& get_spacing() { return spacing_; }
		Origin& get_origin() { return origin_; }
		int get_nvox() { return size_[0] * size_[1] * size_[2]; }
		float* get_voxels() { return voxels_; }

		void save_volume(const std::string& fn);
		void load_volume(const std::string& fn);

	private:
		Size size_;
		Spacing spacing_;
		Origin origin_;
		float* voxels_;

	};
	class pde_export DoseCurve {
	public:
		static std::shared_ptr<DoseCurve> New();
		SetGetMacro(std::vector<double>, position);
		SetGetMacro(std::vector<double>, dose);
		SetGetMacro(int, type); //0: idd, 1:profile_x, 2:profile_y
		SetGetMacro(double, energy); 
		SetGetMacro(double, z); 



	};
}
